#include "stomped_reality/Logger.h"
#include "stomped_reality/render_system/GLFunctionBase.h"
#include "stomped_reality/render_system/LinuxRenderSystem.h"
namespace StompedReality
{
namespace Graphics
{
LinuxRenderSystem::LinuxRenderSystem( )
{
  this->dpy = 0;
  this->m_RenderFunctions = new StompedReality::Graphics::functions::GLFunctionBase( );
}

LinuxRenderSystem::~LinuxRenderSystem( )
{
}

bool LinuxRenderSystem::InitWindow ( int width, int height, bool fullscreen, const char* title )
{
  GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
  dpy = XOpenDisplay( NULL );
  if(dpy == NULL)
  {
    LogCallFunctionError( "LinuxRenderSystem", "InitWindow", "XOpenDisplay failed" );
    return false;
  }
  root = DefaultRootWindow( dpy );
  vi = glXChooseVisual( dpy, 0, att );
  if(vi == NULL) {
    LogCallFunctionError( "LinuxRenderSystem", "InitWindow", "glXChooseVisual failed" );
    return false;
  }
  cmap = XCreateColormap( dpy, root, vi->visual, AllocNone );
  swa.colormap = cmap;
  swa.event_mask = ExposureMask | KeyPressMask | KeyRelease | DestroyNotify | StructureNotifyMask;
  win = XCreateWindow( dpy, root, 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask,
                       &swa );
  XMapWindow( dpy, win );

  //XStoreName(dpy, win, title);
  Atom wmDelete = XInternAtom( dpy, "WM_DELETE_WINDOW", True );
  XSetWMProtocols( dpy, win, &wmDelete, 1 );
  XSetStandardProperties( dpy, win, title,
                          title, None, NULL, 0, NULL );
  glc = glXCreateContext( dpy, vi, NULL, GL_TRUE );
  glXMakeCurrent( dpy, win, glc );
  return true;
}

bool LinuxRenderSystem::CloseWindow( )
{
  if (this->dpy != NULL) {
    glXMakeCurrent( dpy, None, NULL );
    glXDestroyContext( dpy, glc );
    XDestroyWindow( dpy, win );

    // XCloseDisplay(dpy);
  }
  dpy = NULL;
  return true;
}

bool LinuxRenderSystem::IsWindowOpen( )
{
  return this->dpy != NULL;
}

bool LinuxRenderSystem::InitGLExtensions( )
{
  // get procedures
  GLExtensions::glGenBuffersARB = ( PFNGLGENBUFFERSARBPROC ) glXGetProcAddress ( ( const GLubyte* ) "glGenBuffersARB" );
  GLExtensions::glBindBufferARB = ( PFNGLBINDBUFFERARBPROC ) glXGetProcAddress ( ( const GLubyte* ) "glBindBufferARB" );
  GLExtensions::glBufferDataARB = ( PFNGLBUFFERDATAARBPROC ) glXGetProcAddress ( ( const GLubyte* ) "glBufferDataARB" );
  GLExtensions::glDeleteBuffersARB = ( PFNGLDELETEBUFFERSARBPROC ) glXGetProcAddress (
      ( const GLubyte* ) "glDeleteBuffersARB" );

  // check procedures
  GLExtensions::glInitialized = GLExtensions::glGenBuffersARB != 0 &&
    GLExtensions::glBindBufferARB != 0 &&
    GLExtensions::glBufferDataARB != 0 &&
    GLExtensions::glDeleteBuffersARB != 0;
  if ( GLExtensions::glInitialized )
  {
    LogCallFunctionInfo( "LinuxRenderSystem", "InitGLExtensions" );
    return true;
  }

  LogCallFunctionError( "LinuxRenderSystem", "InitGLExtensions", "failed" );
  return false;
}

void LinuxRenderSystem::SwapBuffer ( )
{
  glXSwapBuffers( dpy, win );
}

}
}